package com.dx_society.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dx_society.domain.User;
import com.dx_society.dto.Result;
import com.dx_society.dto.UserDTO;
import com.dx_society.service.UserService;
import com.dx_society.mapper.UserMapper;
import com.dx_society.utils.RSASecurityUtils;
import com.dx_society.utils.RegexUtils;
import com.dx_society.utils.UserHolder;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.dx_society.utils.RedisConstants.*;

/**
 * @author 韶光善良君
 * @description 针对表【dx_user(用户表)】的数据库操作Service实现
 * @createDate 2024-07-01 10:15:34
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {
    @Resource
    RSASecurityUtils rsaSecurityUtils;
    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Override
    public Result login(Long userId, String passRsa) {
        // 4.符合，根据邮箱号查找
        User user = getById(userId);
        // 5.判断用户是否存在
        if (user == null) {
            return Result.fail("用户不存在");
        }
        // 5.1密码校验
        // 5.1.1密码解密
        String password = rsaSecurityUtils.decrypt(passRsa);
        String password2 = rsaSecurityUtils.decrypt(user.getPassword());
        if (!password2.equals(password)) {
            // 5.2密码错误
            return Result.fail("密码错误");
        }
        // 6.保存user到redis
        // 6.1 生成token
        String token = UUID.randomUUID().toString(true);
        // 6.2 将user转为map存储
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(),
                CopyOptions.create()
                        .setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));

        // 6.3 存储
        stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY + token, userMap);
        // 6.4 设置token有效期
        stringRedisTemplate.expire(LOGIN_USER_KEY + token, LOGIN_USER_TTL, TimeUnit.MINUTES);

        // 获取当前日期精确到天
        String today = DateUtil.today();
        // 6.5 存储到hyperLog
        stringRedisTemplate.opsForHyperLogLog().add(USER_UV_KEY + today, String.valueOf(userId));
        // 6.6 设置uv有效期 30天
        stringRedisTemplate.expire(USER_UV_KEY + today, USER_UV_TTL, TimeUnit.HOURS);
        // 7.返回token
        return Result.ok(token);
    }

    public Result register(Long userId, String username, String passRsa) {
        // 4.符合，根据邮箱查询用户
        User user = getById(userId);
        // 5.判断用户是否存在
        if (user != null) {
            return Result.fail("用户已存在");
        }
        // 5.1判断密码格式
        String password2 = rsaSecurityUtils.decrypt(passRsa);
        if (RegexUtils.isPasswordInvalid(password2)) {
            return Result.fail("密码格式错误");
        }
        // 6.保存用户到数据库
        user = new User();
        user.setUserid(userId);
        user.setUsername(username);
        user.setPassword(passRsa);
        user.setRole(2);
        save(user);

        // 6.保存user到redis
        // 6.1 生成token
        String token = UUID.randomUUID().toString(true);
        // 6.2 将user转为map存储
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(),
                CopyOptions.create()
                        .setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));

        // 6.3 存储
        stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY + token, userMap);
        // 6.4 设置token有效期
        stringRedisTemplate.expire(LOGIN_USER_KEY + token, LOGIN_USER_TTL, TimeUnit.MINUTES);

        // 获取当前日期精确到天
        String today = DateUtil.today();
        // 6.5 存储到hyperLog 存储uv
        stringRedisTemplate.opsForHyperLogLog().add(USER_UV_KEY + today, String.valueOf(userId));
        // 6.6 设置uv有效期 30天
        stringRedisTemplate.expire(USER_UV_KEY + today, USER_UV_TTL, TimeUnit.HOURS);

        // 7.返回token
        return Result.ok(token);
    }

    @Override
    public Result getUV(String date) {
        UserDTO user;
        Integer role;
        try {
            user = UserHolder.getUser();
            role = user.getRole();
        } catch (Exception e) {
            return Result.fail("请先登录");
        }

        if (role != 0) {
            return Result.fail("权限不足");
        }

        //date格式 2024-05-20
        String redisKey = USER_UV_KEY + date;

        // 获取当前日期的UV
        Long uvCount = stringRedisTemplate.opsForHyperLogLog().size(redisKey);

        // 返回结果
        return Result.ok(uvCount);
    }
}




